package cz.uhk.domain;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import cz.uhk.service.Stomo;

public class Bludiste implements Serializable{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 8216051376019365621L;
	private byte[][] reprezentace;
	private final int SIRKA = 30;
	private final int VYSKA = 30;
	private boolean isMys = false;
	private boolean isSyr = false;
	private float[][] incidence;
	
	private boolean jednaMistnost = false;
	private boolean syrAMysJednaMistnost = false;
	
	private float strDoba;
	
	private Stomo stomo;
	
	private List<Mistnost> mistnosti = new ArrayList<Mistnost>();
	
	public Bludiste(){
		this.reprezentace = new byte[VYSKA][SIRKA];
		naplnReprezentaci();
	}
	
	public void naplnReprezentaci(){
		for(int i = 0; i < VYSKA; i++){
			for(int j = 0; j < SIRKA; j++){
				if(kraj(i, j)){
					reprezentace[i][j] = 1;
				}
				else{
					reprezentace[i][j] = 0;
				}
			}
		}
	}
	
	public void vycistiBludiste(){
		for(int i = 0; i<VYSKA; i++){
			for(int j = 0; j < SIRKA; j++){
				if(reprezentace[i][j] > 2) reprezentace[i][j] = 0;
			}
		}
		isMys = false;
		isSyr = false;
		jednaMistnost = false;
		syrAMysJednaMistnost = false;
		mistnosti.clear();
		strDoba = 0;
	}
	
	private boolean kraj(int i, int j){
		boolean isKraj = false;
		
		if(i==0 || j==0 || i == (VYSKA-1) || j==(VYSKA-1)){
			isKraj = true;
		}
		
		return isKraj;
	}
	
	private void tiskniReprezentaci(){
		String radek;
		for(int i = 0; i<VYSKA; i++){
			radek = "";
			for(int j = 0; j < SIRKA; j++){
				radek = radek + reprezentace[i][j];
			}
			System.out.println(radek);
		}
	}
	
	public void tiskniIncidenci(){
		String radek;
		for(int i = 0; i<mistnosti.size(); i++){
			System.out.print("    "+(i+5)+"  ");
		}
		System.out.print("\n");
		for(int i = 0; i<mistnosti.size(); i++){
			radek = "";
			for(int j = 0; j < mistnosti.size(); j++){
				radek = radek + incidence[i][j]+" ";
			}
			System.out.println(i+5+": "+radek);
		}
	}
	
	public void prectiBludisteZReprezentace(){
		rozpoznejMistnosti();
		if(mistnosti.size() == 1){
			jednaMistnost = true;
		}else{
			vycistiDvere();
			rozpoznejDvere();
			vypocitejIncidenci();
			//stomo = new Stomo();
			//strDoba = stomo.vypocitejTeorStrDobuPruchodu(getIncidence(), getCisloMysi()-5,getCisloSyru()-5);
			
		}
		
	}
	
	public void rozpoznejDvere(){
		Dvere d;
		Mistnost m1;
		Mistnost m2;
		for(int i = 1; i<VYSKA-1; i++){
			for(int j = 1; j < SIRKA-1; j++){
				if(reprezentace[i][j]==2){
					if(dvereHorizont(i, j)){
						d = new Dvere(i,j);
						m1 = getMistnostByCislo(reprezentace[i-1][j]);
						m2 = getMistnostByCislo(reprezentace[i+1][j]);
						d.setMistnost1(m1);
						d.setMistnost2(m2);
						m1.getDvere().add(d);
						m2.getDvere().add(d);
					}
					else{
						m1 = getMistnostByCislo(reprezentace[i][j-1]);
						m2 = getMistnostByCislo(reprezentace[i][j+1]);
						d = new Dvere(i,j);
						d.setMistnost1(m1);
						d.setMistnost2(m2);
						m1.getDvere().add(d);
						m2.getDvere().add(d);
					}
				}
			}
			
		}
	}
	
	public void vycistiDvere(){
		for (Mistnost m : mistnosti) {
			m.getDvere().clear();
		}
	}
	
	public boolean dvereHorizont(int i, int j){
		boolean horizont = false;
		if((reprezentace[i][j-1] == 1) && (reprezentace[i][j+1] == 1)){
			horizont = true;
		}
		else if ((reprezentace[i-1][j] == 1) && (reprezentace[i+1][j] == 1)){
			horizont = false;
		}
		return horizont;
	}
	
	public void rozpoznejMistnosti(){
		
		for(int i = 1; i<VYSKA-1; i++){
			for(int j = 1; j < SIRKA-1; j++){
				if(reprezentace[i][j]==0){
					Mistnost m = new Mistnost(mistnosti.size()+5);
					seminko(i,j,m);
					mistnosti.add(m);
				}
			}
			
		}
				
	}
	
	public void seminko(int r, int s, Mistnost m){
		
		if(reprezentace[r][s]==0)reprezentace[r][s] = (byte) (mistnosti.size()+5);
		m.getBody().add(new Bod(r,s));
		
		if(reprezentace[r][s] == 3) m.setMouse(true);
		if(reprezentace[r][s] == 4) m.setSyr(true);
		
		if(m.isMouse() && m.isSyr()){
			syrAMysJednaMistnost = true;
		}
		
		byte horni = reprezentace[r-1][s];
		byte pravy = reprezentace[r][s+1];
		byte dolni = reprezentace[r+1][s];
		byte levy = reprezentace[r][s-1];
		
		if(horni==0 || horni == 3 || horni == 4){
			seminko(r-1,s,m);
		}
		
		if(pravy==0 || pravy == 3 || pravy == 4){
			seminko(r,s+1,m);
		}
		
		if(dolni==0 || dolni == 3 || dolni == 4){
			seminko(r+1,s,m);
		}
		
		if(levy==0 || levy == 3 || levy == 4){
			seminko(r,s-1,m);
		}
	}
	
	
	public Mistnost getMistnostByCislo(int cislo){
		for (Mistnost m : mistnosti) {
			if(m.getCislo()==cislo) return m;
		}
		return null;
	}
	
	public void vypocitejIncidenci(){
		incidence = new float[mistnosti.size()][mistnosti.size()];
		
		Mistnost m;
		for(int i = 0; i < mistnosti.size(); i++){
			m = mistnosti.get(i);
			for(int j = 0; j < m.getDvere().size(); j++){
				
				Dvere d = m.getDvere().get(j); 
				float inc = 1/(float)m.getDvere().size();
				int op = d.getOpacnouMistnost(m).getCislo()-5;
				//if(i==op) break;
				incidence[i][op] += inc;
				
			}
		}
		
	}
	
	public Mistnost getMistnostMys(){
		for (Mistnost m : mistnosti) {
			if(m.isMouse()) return m;
		}
		return null;
	}
	
	public Mistnost getMistnostSyr(){
		for (Mistnost m : mistnosti) {
			if(m.isSyr()) return m;
		}
		return null;
	}
	
	public int getCisloMysi(){
		return getMistnostMys().getCislo();
	}
	
	public int getCisloSyru(){
		return getMistnostSyr().getCislo();
	}
	
	// gettry setry
	public byte[][] getReprezentace() {
		return reprezentace;
	}

	public void setReprezentace(byte[][] reprezentace) {
		this.reprezentace = reprezentace;
	}

	public int getSIRKA() {
		return SIRKA;
	}

	public int getVYSKA() {
		return VYSKA;
	}

	public boolean isMys() {
		return isMys;
	}

	public void setMys(boolean isMys) {
		this.isMys = isMys;
	}

	public boolean isSyr() {
		return isSyr;
	}

	public void setSyr(boolean isSyr) {
		this.isSyr = isSyr;
	}

	public List<Mistnost> getMistnosti() {
		return mistnosti;
	}

	public void setMistnosti(List<Mistnost> mistnosti) {
		this.mistnosti = mistnosti;
	}

	public float[][] getIncidence() {
		return incidence;
	}

	public void setIncidence(float[][] incidence) {
		this.incidence = incidence;
	}

	public float getStrDoba() {
		return strDoba;
	}

	public void setStrDoba(float strDoba) {
		this.strDoba = strDoba;
	}

	public boolean isJednaMistnost() {
		return jednaMistnost;
	}

	public void setJednaMistnost(boolean jednaMistnost) {
		this.jednaMistnost = jednaMistnost;
	}

	public boolean isSyrAMysJednaMistnost() {
		return syrAMysJednaMistnost;
	}

	public void setSyrAMysJednaMistnost(boolean syrAMysJednaMistnost) {
		this.syrAMysJednaMistnost = syrAMysJednaMistnost;
	}
	
	

}
